package com.fy.proj3_deepseek_api.service;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;

@Service
public class DeepseekService {

    // 从配置文件中读取API Key
    @Value("${deepseek.api.key}")
    private String apiKey;

    // DeepSeek API 端点  API端点 ：DeepSeek官方的聊天补全API地址
    private static final String DEEPSEEK_API_URL = "https://api.deepseek.com/chat/completions";
    
    // JSON处理工具
    private final ObjectMapper objectMapper;
    
    // HTTP客户端
    private final OkHttpClient client;
    
    public DeepseekService() {
        // 初始化ObjectMapper
        this.objectMapper = new ObjectMapper();
        
        // 配置OkHttpClient，设置超时时间为120秒（reasoner模型需要更长时间）
        this.client = new OkHttpClient.Builder()
                .connectTimeout(Duration.ofSeconds(120))
                .readTimeout(Duration.ofSeconds(120))
                .writeTimeout(Duration.ofSeconds(120))
                .build();

        //- 连接超时 ：120秒，建立TCP连接的最大等待时间
//                - 读取超时 ：120秒，读取响应数据的最大等待时间
//                - 写入超时 ：120秒，发送请求数据的最大等待时间
//        特别说明 ：120秒超时是针对DeepSeek的 reasoner 模型设计的，该模型需要更长的处理时间。
    }

    /**
     * 调用DeepSeek API生成回复（直接使用OkHttpClient，确保兼容性和可靠性）
     * @param prompt 用户的提示内容
     * @param model 使用的模型名称
     * @param temperature 温度参数
     * @param maxTokens 最大令牌数
     * @return 大模型生成的回复内容
     * @throws IOException 当API调用失败时抛出
     */
    public String generateResponse(String prompt, String model, float temperature, int maxTokens) throws IOException {
        try {
            // 构建请求体
            Map<String, Object> requestBodyMap = new HashMap<>();
            requestBodyMap.put("model", model);
            requestBodyMap.put("temperature", temperature);
            requestBodyMap.put("max_tokens", maxTokens);
            
            // 构建messages数组
            Map<String, String> message = new HashMap<>();
            message.put("role", "user");
            message.put("content", prompt);
            requestBodyMap.put("messages", new Object[]{message});
            
            // 转换为JSON字符串
            String jsonRequestBody = objectMapper.writeValueAsString(requestBodyMap);
            
            // 创建请求体
            RequestBody body = RequestBody.create(
                    jsonRequestBody,
                    MediaType.parse("application/json")
            );
            
            // 创建请求
            Request request = new Request.Builder()
                    .url(DEEPSEEK_API_URL)
                    .header("Authorization", "Bearer " + apiKey)
                    .header("Content-Type", "application/json")
                    .post(body)
                    .build();
            
            // 发送请求并获取响应
            Response response = client.newCall(request).execute();
            try (response) {
                if (!response.isSuccessful()) {
                    String errorBody = response.body().string();
                    System.err.println("API调用失败: 状态码 " + response.code() + ", 响应: " + errorBody);
                    throw new IOException("API调用失败: 状态码 " + response.code() + ", 响应: " + errorBody);
                }
                
                // 解析响应
                String responseBody = response.body().string();
                System.out.println("API响应: " + responseBody);
                JsonNode rootNode = objectMapper.readTree(responseBody);
                
                // 提取生成的内容
                if (rootNode.has("choices") && rootNode.get("choices").isArray() && rootNode.get("choices").size() > 0) {
                    JsonNode choiceNode = rootNode.get("choices").get(0);
                    if (choiceNode.has("message") && choiceNode.get("message").has("content")) {
                        return choiceNode.get("message").get("content").asText();
                    }
                }
                
                throw new IOException("未获取到回复内容或响应格式不符合预期");
            }
        } catch (Exception e) {
            throw new IOException("API调用失败: " + e.getMessage(), e);
        }
    }
}